<?php
// 登录
class LOGIN
{
    // 参数描述
    /*{{{*/
    /*
       +---------------------------------------------------------------+
       |输入                                                           |
       +-------------------------------------------+-------------------+
       |参数                                       |描述               |
       +-------------------------------------------+-------------------+
       |'loginname'=>账户名                        |                   |
       +-------------------------------------------+-------------------+

       +---------------------------------------------------------------+
       |输出                                                           |
       +-------------------------------------------+-------------------+
       |参数                                       |描述               |
       +-------------------------------------------+-------------------+
       |'errcode'=>SOAR_ERR::OK                    |成功               |
       +-------------------------------------------+-------------------+
     */
    /*}}}*/

    public function call($request)
    {/*{{{*/
        if(($dbconn=worker::get_dbconn('db1')) == false)
            return false;

        if(self::check_para($request) == false)
        {
            return array('errcode'=>SOAR_ERR::PARA);
        }
        $loginname=trim($request['loginname']);

        $res=self::check_memb($dbconn, $loginname);
        if($res === false)
        {
            return false;
        }
        if(isset($res['errcode']))
        {
            return array('errcode'=>$res['errcode']);
        }
        $uuid=$res['uuid'];
        $nickname=$res['nickname'];

        $res=self::increase_login_times($dbconn, $uuid);
        if($res === false)
        {
            return false;
        }
        if(isset($res['errcode']))
        {
            return array('errcode'=>$res['errcode']);
        }

        $res=self::init_session($uuid, $loginname, $nickname);
        if(isset($res['errcode']))
        {
            return array('errcode'=>$res['errcode']);
        }

        self::add_cache($uuid, $loginname, $nickname);

        return array('errcode'=>SOAR_ERR::OK);
    }/*}}}*/

    private function check_para($request)
    {/*{{{*/
        if(!isset($request['loginname']))
        {
            errlog::add("%s: loginname unset", __METHOD__);
            return false;
        }
        $loginname=trim($request['loginname']);
        if(strlen($loginname) > misc::NAME_SIZE)
        {
            errlog::add("%s: loginname(%s) invalid",
                    __METHOD__, $loginname);
            return false;
        }

        return true;
    }/*}}}*/

    private function check_memb($dbconn, $loginname)
    {/*{{{*/
        $stmt=$dbconn->prepare(
                "select uuid,nickname,login_times ".
                "from memb_info where loginname=?"
                );
        if($stmt === false)
        {
            errlog::add("%s: prepare select loginname(%s) fail:%d %s",
                    __METHOD__, $loginname,
                    $dbconn->errno, $dbconn->error);
            return false;
        }
        $stmt->bind_param('s', $loginname);
        if($stmt->execute() == false)
        {
            errlog::add("%s: select loginname(%s) fail:%d %s",
                    __METHOD__, $loginname,
                    $stmt->errno, $stmt->error);
            return false;
        }
        $stmt->store_result();
        if($stmt->num_rows() == 0)
        {
            $res=array('errcode'=>'MEMB_NOT_FOUND');
        }
        else
        {
            $stmt->bind_result($uuid, $nickname, $login_times);
            $stmt->fetch();
            $res=array('uuid'=>$uuid, 'nickname'=>$nickname,
                    'login_times'=>$login_times);
        }
        $stmt->close();

        return $res;
    }/*}}}*/

    private function increase_login_times($dbconn, $uuid)
    {/*{{{*/
        //    try
        //    {
        //        $stmt=$dbconn->prepare("update memb_info set ".
        //                "update_ts=sysdate(),login_times=login_times+1 ".
        //                "where loginname=:loginname");
        //        $stmt->execute(array(':loginname'=>$loginname));
        //        if($stmt->rowCount() == 0)
        //            $res=array('errcode'=>'MEMB_NOT_FOUND');
        //        else
        //            $res=array('errcode'=>SOAR_ERR::OK);
        //    }
        //    catch(PDOException $e)
        //    {
        //        errlog::add("%s: worker(%d) update memb_info fail: %s",
        //                __METHOD__, worker::$worker_idx,
        //                $e->getMessage()); 
        //        return false;
        //    }

        $stmt=$dbconn->prepare("update memb_info set ".
                "update_ts=sysdate(),login_times=login_times+1 ".
                "where uuid=?");
        if($stmt === false)
        {
            errlog::add("%s: prepare update memb_info(%d) fail: %d %s",
                    __METHOD__, $uuid, $dbconn->errno, $dbconn->error);
            return false;
        }
        $stmt->bind_param('i', $uuid);
        if($stmt->execute() == false)
        {
            errlog::add("%s: update memb_info(%d) fail: %d %s",
                    __METHOD__, $uuid, $stmt->errno, $stmt->error);
            return false;
        }
        if($stmt->affected_rows == 0)
        {
            $res=array('errcode'=>'MEMB_NOT_FOUND');
        }
        else
        {
            $res=array();
        }
        $stmt->close();

        return $res;
    }/*}}}*/

    private function init_session($uuid, $loginname, $nickname)
    {/*{{{*/
        $sn=worker::get_svcnode('session');
        if($sn === false)
        {
            errlog::add("%s: svcnode session not found", __METHOD__);
            return array('errcode'=>SOAR_ERR::COMM_FAIL);
        }

        $res=$sn->call('CREATE', array($uuid));
        if($res === false)
        {
            errlog::add("%s: session(%d) create fail", __METHOD__, $uuid);
            return array('errcode'=>SOAR_ERR::COMM_FAIL);
        }
        $errcode=$res['errcode'];
        if($errcode != SOAR_ERR::OK &&
                $errcode != SOAR_ERR::SESSION_EXIST)
        {
            errlog::add("%s: session(%d) create fail, errcode:%s",
                    __METHOD__, $uuid, $errcode);
            return array('errcode'=>$errcode);
        }
        $sid=$res['paras'][0];

        $pairs=array();
        $pairs['uuid']=$uuid;
        $pairs['loginname']=$loginname;
        $pairs['nickname']=$nickname;
        $paras=array();
        $paras[]=$sid;
        $paras[]=count($pairs);
        foreach($pairs as $k=>$v)
        {
            $paras[]=$k;
            $paras[]=$v;
        }
        $res=$sn->call('PUTKEY', $paras);
        if($res === false)
        {
            errlog::add("%s: session(%d) putkey fail",
                    __METHOD__, $uuid);
            return array('errcode'=>SOAR_ERR::COMM_FAIL);
        }
        $errcode=$res['errcode'];
        if($errcode != SOAR_ERR::OK)
        {
            errlog::add("%s: session(%d) putkey fail, errcode:%s",
                    __METHOD__, $uuid, $errcode);
            return array('errcode'=>$errcode);
        }

        return array();
    }/*}}}*/

    private function add_cache($uuid, $loginname, $nickname)
    {/*{{{*/
        $mc=worker::get_memcache('cache1');
        if($mc === false)
        {
            errlog::add("%s: memcache cache1 not found", __METHOD__);
            return false;
        }

        $key="uuid:$uuid";
        $val=array('loginname'=>$loginname, 'nickname'=>$nickname);
        if($mc->add($key, $val) == false)
        {
            errlog::add("%s: uuid(%d) duplicate",
                    __METHOD__, $uuid);
        }
        $key="loginname:$loginname";
        $val=array('uuid'=>$uuid, 'nickname'=>$nickname);
        if($mc->add($key, $val) == false)
        {
            errlog::add("%s: loginname(%s) duplicate",
                    __METHOD__, $loginname);
        }
        $key="nickname:$nickname";
        $val=array('uuid'=>$uuid, 'loginname'=>$loginname);
        if($mc->add($key, $val) == false)
        {
            errlog::add("%s: nickname(%s) duplicate",
                    __METHOD__, $nickname);
        }

        return true;
    }/*}}}*/
}
?>
